<%#
 Copyright 2013-2018 the original author or authors from the JHipster project.

 This file is part of the JHipster project, see https://www.jhipster.tech/
 for more information.

 Licensed under the Apache License, Version 2.0 (the "License");
 you may not use this file except in compliance with the License.
 You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

 Unless required by applicable law or agreed to in writing, software
 distributed under the License is distributed on an "AS IS" BASIS,
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 See the License for the specific language governing permissions and
 limitations under the License.
-%>
# Consul HA cluster
#
# Based on https://github.com/kubernetes/charts/tree/14bee1e456c1789d1ebdfc2dc7e3ae2b9ea930ce/incubator/consul
# Note that as this is based on a StatefulSet, it will only work on Kubernetes >= 1.5
#
# By default, Consul and its UI is not accessible from outside the cluster for security reasons
# You can setup temporary access to it on localhost:8500 by running :
#   kubectl port-forward consul-0 8500
#
# To check the state of your Consul cluster :
#   kubectl exec consul-0 -- sh -c 'consul members'
#
# To scale your Consul cluster :
#   kubectl patch statefulset/consul -p '{"spec":{"replicas": 5}}'
#
# To check the state of every node
#   for i in {0..4}; do kubectl exec consul-$i -- sh -c 'consul members'; done
apiVersion: v1
kind: Secret
metadata:
  name: gossip-key
  namespace: <%= kubernetesNamespace %>
type: Opaque
data:
  gossip-key: SUcwRzF3N2c4QW5YMDA3cUEwWElqMTJG # a 24 chars base64 encoded string
---
apiVersion: v1
kind: Service
metadata:
  name: consul
  namespace: <%= kubernetesNamespace %>
  labels:
    app: consul
  annotations:
    service.alpha.kubernetes.io/tolerate-unready-endpoints: "true"
spec:
  ports:
  - name: http
    port: 8500
  - name: rpc
    port: 8400
  - name: tcp-serflan
    protocol: "TCP"
    port: 8301
  - name: udp-serflan
    protocol: "UDP"
    port: 8301
  - name: tcp-serfwan
    protocol: "TCP"
    port: 8302
  - name: udp-serfwan
    protocol: "UDP"
    port: 8302
  - name: server
    port: 8300
  - name: consuldns
    port: 8600
  clusterIP: None
  selector:
    app: consul
---
apiVersion: apps/v1beta1
kind: StatefulSet
metadata:
  name: consul
  namespace: <%= kubernetesNamespace %>
spec:
  serviceName: consul
  replicas: 3
  template:
    metadata:
      name: consul
      labels:
        app: consul
    spec:
      securityContext:
        fsGroup: 1000
      containers:
      - name: "consul"
        image: <%= DOCKER_CONSUL %>
        imagePullPolicy: "Always"
        ports:
        - name: http
          containerPort: 8500
        - name: rpc
          containerPort: 8400
        - name: tcp-serflan
          protocol: "TCP"
          containerPort: 8301
        - name: udp-serflan
          protocol: "UDP"
          containerPort: 8301
        - name: tcp-serfwan
          protocol: "TCP"
          containerPort: 8302
        - name: udp-serfwan
          protocol: "UDP"
          containerPort: 8302
        - name: server
          containerPort: 8300
        - name: consuldns
          containerPort: 8600
        resources:
          requests:
            cpu: "100m"
            memory: "512Mi"
        env:
        - name: INITIAL_CLUSTER_SIZE
          value: "3"
        - name: PETSET_NAME
          value: "consul"
        - name: PETSET_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        volumeMounts:
        - name: datadir
          mountPath: /var/lib/consul
        - name: gossip-key
          mountPath: /etc/consul/secrets
          readOnly: true
        command:
          - "/bin/sh"
          - "-ec"
          - |
            IP=$(hostname -i)

            if [ -e /etc/consul/secrets/gossip-key ]; then
              echo "{\"encrypt\": \"$(base64 /etc/consul/secrets/gossip-key)\"}" > /etc/consul/encrypt.json
              GOSSIP_KEY="-config-file /etc/consul/encrypt.json"
            fi

            for i in $(seq 0 $((${INITIAL_CLUSTER_SIZE} - 1))); do
                while true; do
                    echo "Waiting for ${PETSET_NAME}-${i}.${PETSET_NAME} to come up"
                    ping -W 1 -c 1 ${PETSET_NAME}-${i}.${PETSET_NAME}.${PETSET_NAMESPACE}.svc.cluster.local > /dev/null && break
                    sleep 1s
                done
            done

            PEERS=""
            for i in $(seq 0 $((${INITIAL_CLUSTER_SIZE} - 1))); do
                PEERS="${PEERS}${PEERS:+ } -retry-join $(ping -c 1 ${PETSET_NAME}-${i}.${PETSET_NAME}.${PETSET_NAMESPACE}.svc.cluster.local | awk -F'[()]' '/PING/{print $2}')"
            done

            exec /bin/consul agent \
              -data-dir=/var/lib/consul \
              -server \
              -ui \
              -bootstrap-expect=${INITIAL_CLUSTER_SIZE} \
              -bind=0.0.0.0 \
              -advertise=${IP} \
              ${PEERS} \
              ${GOSSIP_KEY} \
              -client=0.0.0.0
      volumes:
      - name: gossip-key
        secret:
          secretName: gossip-key
      #readinessProbe:
      #  httpGet:
      #    path: /v1/health/service/consul
      #    port: 8500
      #  initialDelaySeconds: 10
      #  timeoutSeconds: 1
  volumeClaimTemplates:
  - metadata:
      name: datadir
      annotations:
        volume.alpha.kubernetes.io/storage-class: anything
    spec:
      accessModes:
        - "ReadWriteOnce"
      resources:
        requests:
          # upstream recommended max is 700M
          storage: "700M"
